package com.sinping.qh.service.redis;

import com.sinping.qh.api.exception.HandlerException;
import com.sinping.qh.api.support.Const;
import com.sinping.qh.api.support.ConstEum;
import com.sinping.qh.domain.user.TokenInfo;
import com.sinping.qh.domain.user.UserInfo;
import com.sinping.qh.dto.mongo.auth.UserSessionDTO;
import com.sinping.qh.repository.mongo.user.TokenRepository;
import com.sinping.qh.repository.mongo.user.UserInfoRepository;
import com.sinping.qh.utils.mapper.JsonMapper;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool;

/**
 * 参考mesi协议
 * se
 * @author zhangjin
 * @create 2018/8/8
 */
@Service
public class RedisService {

    @Value("${fx.session.ttl}")
    private int ttlDefault;

    @Autowired
    private JedisPool jedisPool;

    @Autowired
    RedisService redisService;

    @Autowired
    UserInfoRepository userInfoRepository;

    @Autowired
    TokenRepository tokenRepository;

    /**********************************************************************************************
     ******************************资源池管理******************************************
     **********************************************************************************************/

    private Jedis getJedis(){
        Jedis resource = jedisPool.getResource();
        return resource;
    }

    private void closeJedis(Jedis resource){
      if(resource!=null)
      {
          resource.close();
      }
    }

    /**********************************************************************************************
     ******************************缓存数据更新操作******************************************
     **********************************************************************************************/
    /**
     * 注意点
     * 一、Modified、Exlusive、Shared、Invalid是依赖于secondKey的,如果secondKey过期,这时是不能修改状态的
     * 否则会出现脏数据
     *
     **/

    public void setUpdate(String key){
//        String newKey= Const.REDISKEYBYAPP+":"+Const.tokenPrefix +key;
        setUpdate(key,RedisCommon.UpdateType.Modified);
    }

    public void setUpdate(String key,RedisCommon.UpdateType updateType){
        Jedis resource=getJedis();
        //如果key值不存在,不能修改状态,会没有意义的
        if(resource.exists(key)) {
            resource.hset(key, updateType.getUpdateName(), RedisCommon.REDIS_TRUE);
        }
        closeJedis(resource);
    }

    /**
     * 过期key
     * @param key
     */
    public void expireKey(String key)
    {
        Jedis resource=getJedis();
        if(resource.exists(key)) {
            resource.expire(key, 0);
        }
        closeJedis(resource);
    }

    /**
     * 检查key是否存在
     * @param key
     */
    public boolean existsKey(String key)
    {
        boolean ret =false;
        Jedis resource=getJedis();
        if(resource.exists(key)) {
            ret=true;
        }
        closeJedis(resource);
        return ret;
    }

    private void hset(String key,RedisCommon.RedisPrimaryKey redisKey,String value){
        Jedis resource=getJedis();
        resource.hset(key,redisKey.getSecorndKey(),value);
        resource.hset(key,RedisCommon.UpdateType.Modified.getUpdateName(),RedisCommon.REDIS_FASLE);
        resource.hset(key,RedisCommon.UpdateType.Exlusive.getUpdateName(),RedisCommon.REDIS_FASLE);
        resource.hset(key,RedisCommon.UpdateType.Shared.getUpdateName(),RedisCommon.REDIS_FASLE);
        resource.hset(key,RedisCommon.UpdateType.Invalid.getUpdateName(),RedisCommon.REDIS_FASLE);
        closeJedis(resource);
    }

    /**********************************************************************************************
     ******************************缓存数据记录区******************************************
     **********************************************************************************************/
    /**
     * 用户基本信息的缓存
     * @param token
     * @return
     */
    public String hgetByUserinfo(String token){
        //新的key规则
        String key= RedisCommon.RedisPrimaryKey.UserSessionByApp.getFirstKey() +token;
        //获取存储的主key字段
        RedisCommon.RedisPrimaryKey redisKey=RedisCommon.RedisPrimaryKey.UserSessionByApp;
        Jedis resource=getJedis();
        String keyValue="" ;
        try {
            keyValue =resource.hget(key,redisKey.getSecorndKey());
            //判断是否有modified状态字段
            String modified = resource.hget(key, RedisCommon.UpdateType.Modified.getUpdateName());
            if (StringUtils.isNotBlank(keyValue) && StringUtils.isBlank(modified)) {
                throw new HandlerException(ConstEum.FAIL, "缓存缺少modified状态");
            }

            if (StringUtils.isNotBlank(keyValue) && !keyValue.equals("null") &&
                    modified.equals(RedisCommon.REDIS_FASLE)) {
                return keyValue;
            }
            //生成sessiondto信息
            TokenInfo tokenInfo = tokenRepository.findTokenInfoByToken(token);
            UserInfo userInfo = userInfoRepository.findOne(tokenInfo.getUserId());
            UserSessionDTO sessionDto = new UserSessionDTO();
            sessionDto.setToken(token);
            sessionDto.setUserInfo(userInfo);

            keyValue = JsonMapper.defaultMapper().toJson(sessionDto);
            hset(key, redisKey, keyValue);
        }catch (Exception e){
            expireKey(key);
        }finally {
            closeJedis(resource);
        }

        return keyValue;
    }
}
